package com.candy.security.jwt.weixin;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

public class WeixinCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter
{
	private boolean postOnly = true;

	public final static String LoginRandomUserPrefix = "login:random:user:";

	private RedisTemplate redisTemplate;

	public WeixinCodeAuthenticationFilter(RedisTemplate redisTemplate) {
		super(new AntPathRequestMatcher("/authentication/weixincode", "POST"));
		this.redisTemplate = redisTemplate;
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException
	{
		if (this.postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		} else {
			String ipAddr = "";//IpUtils.getIpAddr(request);
			String ipTryRedisKey = "login:try:" + ipAddr;
			Object timeCount = redisTemplate.opsForValue().get(ipTryRedisKey);
			if(timeCount!=null && (Integer) timeCount>5)
			{
				throw new UsernameNotFoundException("您登录的错误次数太多，账号锁定30分钟");
			}
			String winxinCode = this.obtainWinxinCode(request);
			if (StringUtils.isEmpty(winxinCode)) {
				throw new UsernameNotFoundException("未获取到微信验证码");
			}
			winxinCode = winxinCode.trim();
			Object openId = redisTemplate.opsForValue().get(LoginRandomUserPrefix + winxinCode);
			if(openId == null)
			{
				if(timeCount == null)
				{
					redisTemplate.opsForValue().set(ipTryRedisKey,1,30L, TimeUnit.MINUTES);
				}
				else
				{
					redisTemplate.opsForValue()
								 .increment(ipTryRedisKey);
				}
				throw new UsernameNotFoundException("微信验证码错误或已过期，请获取新的验证码");
			}
			redisTemplate.delete(LoginRandomUserPrefix + winxinCode);
			// 生成token
			WeixinCodeAuthenticationToken authRequest = new WeixinCodeAuthenticationToken(String.valueOf(openId));
			authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
			// 调用 AuthenticationManager
			return this.getAuthenticationManager().authenticate(authRequest);
		}
	}

	/**
	 *  获取微信验证码
	 * @param request
	 * @return
	 */
	@Nullable
	protected String obtainWinxinCode(HttpServletRequest request) {
		return request.getParameter("weixincode");
	}
}
